// Decompiled on 周六 2月 22 19:31:49 CST 2025 with Zomboid Decompiler v0.1.3 using Vineflower.
package zombie.characters;

import java.util.ArrayList;
import java.util.Comparator;
import java.util.HashSet;
import zombie.core.Core;
import zombie.core.math.PZMath;
import zombie.iso.IsoUtils;
import zombie.network.GameServer;
import zombie.popman.ObjectPool;
import zombie.util.list.PZArrayUtil;

public final class ZombieVocalsManager {
    public static final ZombieVocalsManager instance = new ZombieVocalsManager();
    private final HashSet<IsoZombie> m_added = new HashSet();
    private final ObjectPool<ZombieVocalsManager.ObjectWithDistance> m_objectPool = new ObjectPool<>(ZombieVocalsManager.ObjectWithDistance::new);
    private final ArrayList<ZombieVocalsManager.ObjectWithDistance> m_objects = new ArrayList();
    private final ZombieVocalsManager.Slot[] m_slots;
    private long m_updateMS = 0L;
    private final Comparator<ZombieVocalsManager.ObjectWithDistance> comp = new Comparator<ZombieVocalsManager.ObjectWithDistance>() {
        public int compare(ZombieVocalsManager.ObjectWithDistance objectWithDistance1, ZombieVocalsManager.ObjectWithDistance objectWithDistance0) {
            return Float.compare(objectWithDistance1.distSq, objectWithDistance0.distSq);
        }
    };

    public ZombieVocalsManager() {
        byte _byte = 20;
        this.m_slots = PZArrayUtil.newInstance(ZombieVocalsManager.Slot.class, _byte, ZombieVocalsManager.Slot::new);
    }

    public void addCharacter(IsoZombie chr) {
        if (!this.m_added.contains(chr)) {
            this.m_added.add(chr);
            ZombieVocalsManager.ObjectWithDistance objectWithDistance = this.m_objectPool.alloc();
            objectWithDistance.character = chr;
            this.m_objects.add(objectWithDistance);
        }
    }

    public void update() {
        if (!GameServer.bServer) {
            long _long = System.currentTimeMillis();
            if (_long - this.m_updateMS >= 500L) {
                this.m_updateMS = _long;

                for (int int0 = 0; int0 < this.m_slots.length; int0++) {
                    this.m_slots[int0].playing = false;
                }

                if (this.m_objects.isEmpty()) {
                    this.stopNotPlaying();
                } else {
                    for (int int1 = 0; int1 < this.m_objects.size(); int1++) {
                        ZombieVocalsManager.ObjectWithDistance objectWithDistance = (ZombieVocalsManager.ObjectWithDistance)this.m_objects.get(int1);
                        IsoZombie isoZombie0 = objectWithDistance.character;
                        objectWithDistance.distSq = this.getClosestListener(isoZombie0.x, isoZombie0.y, isoZombie0.z);
                    }

                    this.m_objects.sort(this.comp);
                    int int2 = PZMath.min(this.m_slots.length, this.m_objects.size());

                    for (int int3 = 0; int3 < int2; int3++) {
                        IsoZombie isoZombie1 = ((ZombieVocalsManager.ObjectWithDistance)this.m_objects.get(int3)).character;
                        if (this.shouldPlay(isoZombie1)) {
                            int int4 = this.getExistingSlot(isoZombie1);
                            if (int4 != -1) {
                                this.m_slots[int4].playSound(isoZombie1);
                            }
                        }
                    }

                    for (int int5 = 0; int5 < int2; int5++) {
                        IsoZombie isoZombie2 = ((ZombieVocalsManager.ObjectWithDistance)this.m_objects.get(int5)).character;
                        if (this.shouldPlay(isoZombie2)) {
                            int int6 = this.getExistingSlot(isoZombie2);
                            if (int6 == -1) {
                                int6 = this.getFreeSlot();
                                this.m_slots[int6].playSound(isoZombie2);
                            }
                        }
                    }

                    this.stopNotPlaying();
                    this.postUpdate();
                    this.m_added.clear();
                    this.m_objectPool.release(this.m_objects);
                    this.m_objects.clear();
                }
            }
        }
    }

    boolean shouldPlay(IsoZombie isoZombie) {
        return isoZombie.getCurrentSquare() != null;
    }

    int getExistingSlot(IsoZombie isoZombie) {
        for (int _int = 0; _int < this.m_slots.length; _int++) {
            if (this.m_slots[_int].character == isoZombie) {
                return _int;
            }
        }

        return -1;
    }

    int getFreeSlot() {
        for (int _int = 0; _int < this.m_slots.length; _int++) {
            if (!this.m_slots[_int].playing) {
                return _int;
            }
        }

        return -1;
    }

    void stopNotPlaying() {
        for (int _int = 0; _int < this.m_slots.length; _int++) {
            ZombieVocalsManager.Slot slot = this.m_slots[_int];
            if (!slot.playing) {
                slot.stopPlaying();
                slot.character = null;
            }
        }
    }

    public void postUpdate() {
    }

    private float getClosestListener(float float5, float float6, float float7) {
        float float0 = Float.MAX_VALUE;

        for (int _int = 0; _int < IsoPlayer.numPlayers; _int++) {
            IsoPlayer isoPlayer = IsoPlayer.players[_int];
            if (isoPlayer != null && isoPlayer.getCurrentSquare() != null) {
                float float1 = isoPlayer.getX();
                float float2 = isoPlayer.getY();
                float float3 = isoPlayer.getZ();
                float float4 = IsoUtils.DistanceToSquared(float1, float2, float3 * 3.0F, float5, float6, float7 * 3.0F);
                if (isoPlayer.Traits.HardOfHearing.isSet()) {
                    float4 *= 4.5F;
                }

                if (float4 < float0) {
                    float0 = float4;
                }
            }
        }

        return float0;
    }

    public void render() {
        if (Core.bDebug) {
        }
    }

    public static void Reset() {
        for (int _int = 0; _int < instance.m_slots.length; _int++) {
            instance.m_slots[_int].stopPlaying();
            instance.m_slots[_int].character = null;
            instance.m_slots[_int].playing = false;
        }
    }

    static final class ObjectWithDistance {
        IsoZombie character;
        float distSq;
    }

    static final class Slot {
        IsoZombie character = null;
        boolean playing = false;

        void playSound(IsoZombie isoZombie) {
            if (this.character != null && this.character != isoZombie && this.character.vocalEvent != 0L) {
                this.character.getEmitter().stopSoundLocal(this.character.vocalEvent);
                this.character.vocalEvent = 0L;
            }

            this.character = isoZombie;
            this.playing = true;
            if (this.character.vocalEvent == 0L) {
                String string = isoZombie.isFemale() ? "FemaleZombieCombined" : "MaleZombieCombined";
                if (!isoZombie.getFMODParameters().parameterList.contains(isoZombie.parameterZombieState)) {
                    isoZombie.parameterZombieState.update();
                    isoZombie.getFMODParameters().add(isoZombie.parameterZombieState);
                    isoZombie.parameterCharacterInside.update();
                    isoZombie.getFMODParameters().add(isoZombie.parameterCharacterInside);
                    isoZombie.parameterPlayerDistance.update();
                    isoZombie.getFMODParameters().add(isoZombie.parameterPlayerDistance);
                }

                isoZombie.vocalEvent = isoZombie.getEmitter().playVocals(string);
            }
        }

        void stopPlaying() {
            if (this.character != null && this.character.vocalEvent != 0L) {
                this.character.getEmitter().stopSoundLocal(this.character.vocalEvent);
                this.character.vocalEvent = 0L;
            }
        }
    }
}
